#!/usr/bin/python3
# -*- coding: utf-8; tab-width: 4; indent-tabs-mode: t -*-

import os
import sys
import time
import shutil
import pathlib
import libtorrent
import lxml.html
import urllib.request
import mirrors.plugin


class Main:

    def __init__(self):
        self.baseUrl = "https://fitgirl-repacks.site"

        self.cfg = mirrors.plugin.params["config"]
        self.dataDir = mirrors.plugin.params["storage-file"]["data-directory"]
        self.torrentDir = os.path.join(self.dataDir, ".torrents")
        self.gameList = []

    def run(self):
        self._fetchGameList()
        self._downloadTorrents()
        self._downloadDataFiles()

    def _fetchGameList(self):
        # FIXME: we can use this page to auto discover all games
        url = os.path.join(self.baseUrl, "all-my-repacks-a-z")

        self.gameList = [
            "dcs-world",
        ]

    def _downloadTorrents(self):
        os.makedirs(self.torrentDir, exist_ok=True)
        for game in self.gameList:
            resp = urllib.request.urlopen(os.path.join(self.baseUrl, game), timeout=60)
            root = lxml.html.parse(resp)
            bFound = False
            for aTag in root.xpath(".//a"):
                if aTag.text == "magnet":
                    Util.magnet2torrent(aTag.get("href"), os.path.join(self.torrentDir, game + ".torrent"))
                    bFound = True
                    break
            if not bFound:
                assert False

    def _downloadDataFiles(self):
        for game in self.gameList:
            gameDataDir = os.path.join(self.dataDir, game)
            os.makedirs(gameDataDir, exist_ok=True)

            # FIXME
            pass


class Util:

    @staticmethod
    def magnet2torrent(magnet_url, torrent_path=None):
        # Parse magnet URI parameters
        params = libtorrent.parse_magnet_uri(magnet_url)
        params.save_path = "/dev/null"                            # so that data won't be downloaded

        # Download torrent info
        session = libtorrent.session()
        handle = session.add_torrent(params)
        while not handle.status().has_metadata:
            time.sleep(1)

        # Download torrent data
        torrent_info = handle.status().torrent_file
        torrent_file = libtorrent.create_torrent(torrent_info)
        if torrent_path is None:
            torrent_path = torrent_info.name() + ".torrent"
        torrent_data = libtorrent.bencode(torrent_file.generate())

        # Save torrent file
        if os.path.isfile(torrent_path) and pathlib.Path(torrent_path).read_bytes() == torrent_data:
            # file already exists, avoid writing
            pass
        else:
            with open(torrent_path, "wb") as f:
                f.write(torrent_data)

    @staticmethod
    def forceDelete(path):
        if os.path.islink(path):
            os.remove(path)
        elif os.path.isfile(path):
            os.remove(path)
        elif os.path.isdir(path):
            shutil.rmtree(path)
        elif os.path.lexists(path):
            os.remove(path)             # other type of file, such as device node
        else:
            pass                        # path does not exist, do nothing

    @staticmethod
    def clearDir(path):
        for fn in os.listdir(path):
            Util.forceDelete(os.path.join(path, fn))


###############################################################################

if __name__ == "__main__":
    with mirrors.plugin.ApiClient() as sock:
        try:
            Main().run()
            sock.progress_changed(100)
        except Exception:
            sock.error_occured(sys.exc_info())
            raise
